//+-----------------------------------------------------------------------------
//
//  CTriangleRenderer
//
//      Subclass of CRenderer that renders a single, spinning triangle
//
//------------------------------------------------------------------------------
#include "StdAfx.h"

struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

//+-----------------------------------------------------------------------------
//
//  Member:
//      CTriangleRenderer ctor
//
//------------------------------------------------------------------------------
CTriangleRenderer::CTriangleRenderer() : CRenderer(), m_pd3dVB(NULL)
{
}

//+-----------------------------------------------------------------------------
//
//  Member:
//      CTriangleRenderer dtor
//
//------------------------------------------------------------------------------
CTriangleRenderer::~CTriangleRenderer()
{
	SAFE_RELEASE(m_pd3dVB);
}

//+-----------------------------------------------------------------------------
//
//  Member:
//      CTriangleRenderer::Create
//
//  Synopsis:
//      Creates the renderer
//
//------------------------------------------------------------------------------
HRESULT
CTriangleRenderer::Create(IDirect3D9* pD3D, IDirect3D9Ex* pD3DEx, HWND hwnd, UINT uAdapter, CRenderer** ppRenderer)
{
	HRESULT hr = S_OK;

	CTriangleRenderer* pRenderer = new CTriangleRenderer();
	IFCOOM(pRenderer);

	IFC(pRenderer->Init(pD3D, pD3DEx, hwnd, uAdapter));

	*ppRenderer = pRenderer;
	pRenderer = NULL;

Cleanup:
	delete pRenderer;

	return hr;
}

//+-----------------------------------------------------------------------------
//
//  Member:
//      CTriangleRenderer::Init
//
//  Synopsis:
//      Override of CRenderer::Init that calls base to create the device and 
//      then creates the CTriangleRenderer-specific resources
//
//------------------------------------------------------------------------------
HRESULT
CTriangleRenderer::Init(IDirect3D9* pD3D, IDirect3D9Ex* pD3DEx, HWND hwnd, UINT uAdapter)
{
	HRESULT hr = S_OK;
	D3DXMATRIXA16 matView, matProj;
	D3DXVECTOR3 vEyePt(0.0f, 0.0f, -5.0f);
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
	{
		// Call base to create the device and render target
		IFC(CRenderer::Init(pD3D, pD3DEx, hwnd, uAdapter));

		// Set up the VB
		CUSTOMVERTEX vertices[] =
		{
			{ -1.0f, -1.0f, 0.0f, 0xffff0000, }, // x, y, z, color
			{  1.0f, -1.0f, 0.0f, 0xff00ff00, },
			{  0.0f,  1.0f, 0.0f, 0xff00ffff, },
		};

		IFC(m_pd3dDevice->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pd3dVB, NULL));

		void* pVertices;
		IFC(m_pd3dVB->Lock(0, sizeof(vertices), &pVertices, 0));
		memcpy(pVertices, vertices, sizeof(vertices));
		m_pd3dVB->Unlock();

		// Set up the camera
		D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
		IFC(m_pd3dDevice->SetTransform(D3DTS_VIEW, &matView));
		D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f);
		IFC(m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj));

		// Set up the global state
		IFC(m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE));
		IFC(m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE));
		IFC(m_pd3dDevice->SetStreamSource(0, m_pd3dVB, 0, sizeof(CUSTOMVERTEX)));
		IFC(m_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX));
	}
Cleanup:
	return hr;
}

//+-----------------------------------------------------------------------------
//
//  Member:
//      CTriangleRenderer::Render
//
//  Synopsis:
//      Renders the rotating triangle
//
//------------------------------------------------------------------------------
HRESULT
CTriangleRenderer::Render()
{
	HRESULT hr = S_OK;
	D3DXMATRIXA16 matWorld;
	{
		IFC(m_pd3dDevice->BeginScene());
		IFC(m_pd3dDevice->Clear(
			0,
			NULL,
			D3DCLEAR_TARGET,
			D3DCOLOR_ARGB(128, 0, 0, 128),  // NOTE: Premultiplied alpha!
			1.0f,
			0
		));

		// Set up the rotation
		UINT  iTime = GetTickCount() % 1000;
		FLOAT fAngle = iTime * (2.0f * D3DX_PI) / 100.0f;
		D3DXMatrixRotationY(&matWorld, fAngle);
		IFC(m_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld));

		IFC(m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1));

		IFC(m_pd3dDevice->EndScene());
	}
Cleanup:
	return hr;
}